package com.example.mqtt_client.config;

import cn.hutool.json.JSONUtil;
import com.example.mqtt_client.entity.User;
import com.sun.org.apache.xml.internal.security.algorithms.implementations.SignatureDSA;
import com.zaxxer.hikari.HikariDataSource;
import io.moquette.broker.security.DBAuthenticator;
import io.moquette.broker.security.IAuthenticator;
import io.moquette.interception.AbstractInterceptHandler;
import io.moquette.interception.messages.InterceptConnectMessage;
import io.moquette.interception.messages.InterceptDisconnectMessage;
import io.moquette.interception.messages.InterceptPublishMessage;
import lombok.Data;
import lombok.SneakyThrows;
import org.apache.commons.codec.binary.Hex;
import org.h2.security.SHA256;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;

import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.sql.*;
import java.util.HashMap;
import java.util.Map;

@Data
@Configuration
public class DBAuthenticatorConfig implements IAuthenticator {


    private final String driver = "com.mysql.cj.jdbc.Driver";
    private final String url="jdbc:mysql://localhost:3306/mqtt?serverTimezone=UTC";
    private final String username ="root";
    private final String password = "wuzheng1319";
    private String digestMethod ="SHA-256";
    private MessageDigest messageDigest;
          /*
    * provide authenticator from SQL database
        Params:
        driver – : jdbc driver class like : "org.postgresql.Driver"
        jdbcUrl – : jdbc url like : "jdbc:postgresql://host:port/dbname"
        sqlQuery – : sql query like : "SELECT PASSWORD FROM USER WHERE LOGIN=?"
        digestMethod – : password encoding algorithm : "MD5", "SHA-1", "SHA-256"
    * */

    @SneakyThrows
    @Override
    public synchronized boolean checkValid(String clientId, String username,byte[] password) {
        Class.forName(driver);

        // Check Username / Password in DB using sqlQuery
        if (username == null || password == null) {
            return false;
        }
        ResultSet resultSet = null;
        PreparedStatement preparedStatement = null;
        Connection conn = null;
        String sqlQuery= "select * from user where username=?";
        try {
            conn = DriverManager.getConnection(url,this.getUsername(),this.getPassword());

            preparedStatement = conn.prepareStatement(sqlQuery);
            preparedStatement.setString(1,username);
            resultSet = preparedStatement.executeQuery();

            messageDigest =MessageDigest.getInstance(digestMethod);
            if (resultSet.next()) {
                final String foundPwq = resultSet.getString("password");
                messageDigest.update(password);
                byte[] digest = messageDigest.digest();
                String encodedPasswd = new String(Hex.encodeHex(digest));
                return foundPwq.equals(encodedPasswd);
            }
        } catch (SQLException sqlex) {
            System.err.println("Error releasing connection to the datasource:==="+sqlex);
        } finally {
            try {
                if (resultSet != null) {
                    resultSet.close();
                }
                if (preparedStatement != null) {
                    preparedStatement.close();
                }
                if (conn != null) {
                    conn.close();
                }
            } catch (SQLException e) {
                System.err.println("Error releasing connection to the datasource:==="+e);
            }
        }
        return false;
    }
}
